<?php
$loader->requireOnce('includes/OutPatientFlow/OutPatientFlowProcessor.class.php');
$loader->requireOnce('includes/ParacliniqueEngine.class.php');
$loader->requireOnce('includes/PatientQueue/AbsQueue.class.php');
$loader->requireOnce('includes/ParacliniqueEngine.class.php');
$loader->requireOnce('controllers/C_Department.class.php');
$loader->requireOnce('controllers/C_Ticket.class.php');
class C_OutPatient extends Controller {
	private $logger ;
    function __construct($template_mod = "general"){
    	parent::Controller();
        if (Celini::getCurrentController() == 'OutPatient') {
            $menu =& Menu::getInstance();
            $menu->currentSection = 'patient';
        }
        $this->template_mod = $template_mod;
        $this->view->path = 'out_patient';
        $this->logger = LoggerManager::getLogger('core.controllers.C_OutPatient');
    }

    public function actionGetNextAvailableServicesAjax() {
    	$ticketId  =   EnforceType::int($_GET['ticketId']);
    	$result = array(
                    'error'     =>  array('code' => CoreErrorCode::NORMAL,
                                          'mess' => ''),
                    'result'    =>  ''
        );
    	$objTicketModel    =   new TicketModel($ticketId);
    	$list      =   $objTicketModel->getNextAvailableModelList();
    	$this->assign('serviceModelList', $list['serviceModelList']);
    	$this->assign('paraclinicalModelList', $list['paraclinicalModelList']);
    	$result['result']['code']  =   "OK";
    	if ((count($list['serviceModelList']) == 0) && (count($list['paraclinicalModelList'])==0)) {
            $result['result']['code']  =   "ERR";
    	}
    	$result['result']['html']  =   $this->view->render('next_service.html');

    	return json_encode($result);
    }

    public function actionPerformNextServiceAjax() {
    	$ticketId  =   EnforceType::int($_POST['ticketId']);
    	$currentItemId =   ORDataObject::factory('QueueItem')->getCurrentServiceItem($ticketId);
    	$itemType  =   $_POST['itemType'];
    	$result    =   array(
                    'error'     =>  array('code' => CoreErrorCode::NORMAL,
                                          'mess' => ''),
                    'result'    =>  ''
        );
        $nextRoom   =   '';
        $this->logger->info("Start action PerformNextServiceAjax {currentItemId='$currentItemId', nextItemType= '$itemType'}");
    	if (strtolower($itemType) == 'service'){
            $nextItemId =   $_POST['serviceItemId'];
            // Step 1: Close the current ticket item
            $objTicketItem  =   ORDataObject::factory('TicketItem');
            $objTicketItem->changeStatus($currentItemId, TicketItem::CLOSED);
            $objTicketItem->close($currentItemId);

            // Step 2: Remove the current item from queue_item
            AbsQueue::removeTicketItem($currentItemId);

            // Step 3: Force the next item in approciate queue (Cashier queue or Encounte queue)
            OutPatientFlowProcessor::performTicketItem($nextItemId);
            $objQueueItem   =   QueueItem::fromTicketItemId($nextItemId);
            $nextRoom       =   Celini::newORDO('Room', $objQueueItem->get('room_id'))->getLocalizedText('name');
    	}
    	else {
            // Step 1: Move the current item from current queue to Waiting queue
            AbsQueue::moveTicketItemToQueue($currentItemId, AbsQueue::WAITING);

            // Step 2: Move paraclinique items to their queues
            $i = 0;
            while(isset($_POST['paraclinicalItemId'][$i])) {
                $objTicketItem  =   Celini::newORDO('TicketItem', $_POST['paraclinicalItemId'][$i]);
                ParacliniqueEngine::startParaClinicTicket($objTicketItem->get_id(), $objTicketItem->get('room_id'));
                $nextRoom   .=   Celini::newORDO('Room', $objTicketItem->get('room_id'))->getLocalizedText('name') .",";
                $i++;
            }
            $nextRoom   =   substr($nextRoom, 0, strlen($nextRoom)-1);
    	}
    	$result['result']['nextRoom']        =   $nextRoom;
    	$result['result']['redirectLink']    =   Celini::link('renderQueue', 'Queue');
    	$this->logger->info("Finish action PerformNextServiceAjax {currentItemId='$currentItemId', nextItemType= '$itemType'}");

    	return json_encode($result);
    }

    public function actionGetTicketContentAjax() {
        $ticketId  =   EnforceType::int($_POST['ticketId']);
        $result    =   array(
                    'error'     =>  array('code' => CoreErrorCode::NORMAL,
                                          'mess' => ''),
                    'result'    =>  array('code' => CoreErrorCode::NORMAL,
                                          'html' => '')
        );
        $serviceList  =   OutPatientFlowProcessor::renderTicketItemListHMLT($ticketId);
        if (empty($serviceList)) {
            $result['result']['code']   =   "ERR";
        }
        $result['result']['html']       =   $serviceList;

        return json_encode($result);
    }

    public function actionConfirmDeleteTicketItemAjax() {
        $ticketItemId   =   EnforceType::int($_POST['ticketItemId']);
        $result    =   array(
                    'error'     =>  array('code' => CoreErrorCode::NORMAL,
                                          'mess' => ''),
                    'result'    =>  ''
        );
        $objTicketItem  =   Celini::newORDO('TicketItem', $ticketItemId);
        $ticketId       =   $objTicketItem->get('ticket_id');
        $currentItemId  =   ORDataObject::factory('QueueItem')->getCurrentServiceItem($ticketId);
        if ($ticketItemId == $currentItemId) {
            $this->assign('deleteCurrentItem', true);
            $objTicketModel =   new TicketModel($ticketId);
            $serviceList    =   $objTicketModel->getNextAvailableServiceModelList($ticketItemId);
            $this->assign('serviceModelList', $serviceList);
            if (count($serviceList) > 0) {
                $result['result']['code']   =   "CUR_OK";
            }
            else {
                $result['result']['code']   =   "CUR_ERR";
            }
        }
        else {
        	$result['result']['code']   =   "NOR_OK";
        }
        $objItemModel   =   new TicketItemModel();
        $objItemModel->setup($ticketItemId);
        $this->assign('serviceName', $objItemModel->getServiceName());
        $this->assign('ticketItemId', $ticketItemId);
        $this->assign('ticketId', $ticketId);
        $result['result']['html']   =   $this->view->render('confirm_delete_item.html');

        return json_encode($result);
    }

    public function actionDeleteTicketItemAndGoNext() {
        $ticketItemId   =   EnforceType::int($_POST['ticketItemId']);
        $ticketId		=	EnforceType::int($_POST['ticketId']);
        $nextItemId     =   '';
        if (isset($_POST['serviceItemId'])) {
            $nextItemId     =   $_POST['serviceItemId'];
        }
        $result    =   array(
                    'error'     =>  array('code' => CoreErrorCode::NORMAL,
                                          'mess' => ''),
                    'result'    =>  ''
        );
        $this->logger->info("Start action DeleteTicketItemAndGoNext {ticketItemId=$ticketItemId, ticketId=$ticketId, nextItemId='$nextItemId'}");
        try {
        	// Delete ticket item
            OutPatientFlowProcessor::deleteTicketItem($ticketItemId);
            // If nextItemId provided, move the next item to appociate queue, else finish the ticket
            if (!empty($nextItemId)) {
            	OutPatientFlowProcessor::performTicketItem($nextItemId);
            }
            else {
            	// Finish ticket
            	OutPatientFlowProcessor::closeItems($ticketId);
            	// Add the first ticket item to Cashier queue
            	$firstItemId	=	ORDataObject::factory('Ticket')->getLastTicketItem($ticketId);
            	$this->logger->debug("First ticket item of ticket {ticketId='$ticketId'}:  '$firstItemId'");
            	$cashierQueue  	=   AbsQueue::getQueue(AbsQueue::CASHIER);
            	$cashierQueue->addTicketItem($firstItemId);
            	$objQueueItem   =   QueueItem::fromTicketItemId($firstItemId);
                $nextRoom       =   Celini::newORDO('Room', $objQueueItem->get('room_id'))->getLocalizedText('name');
            	$result['result']['nextRoom']  		=   $nextRoom;
            	$result['result']['redirectLink']   =   Celini::link('renderQueue', 'Queue');
            }
        }
        catch (Exception $ex) {
            $result['error']['code']    =   CoreErrorCode::COMMON_ERROR;
            $result['error']['mess']    =   CoreErrorCode::getErrorMess(CoreErrorCode::COMMON_ERROR);
            $this->logger->error("Action DeleteTicketItemAndGoNext failed. Error message: " . $ex->getMessage());
        }
        $this->logger->info("Finish action DeleteTicketItemAndGoNext {ticketItemId=$ticketItemId, ticketId=$ticketId, nextItemId='$nextItemId'}");

        return json_encode($result);
    }

    public function actionDeleteTicketItemAjax() {
        $ticketItemId   =   $_POST['ticketItemId'];
        $result    =   array(
                    'error'     =>  array('code' => CoreErrorCode::NORMAL,
                                          'mess' => ''),
                    'result'    =>  ''
        );
        $this->logger->info("Start action DeleteTicketItemAjax {ticketItemId=$ticketItemId}");
        $result =   OutPatientFlowProcessor::deleteTicketItem($ticketItemId);
        $this->logger->info("Finish action DeleteTicketItemAjax {ticketItemId=$ticketItemId}");
        return json_encode($result);
    }

    public function actionLoadServiceEditPageAjax($ticketId = 0) {
        if (isset($_GET['ticketId'])) {
        	$ticketId  =   EnforceType::int($_GET['ticketId']);
        }
        $result    =   array(
                    'error'     =>  array('code' => CoreErrorCode::NORMAL,
                                          'mess' => ''),
                    'result'    =>  ''
        );
        $this->logger->info("Start action LoadServiceEditPageAjax {ticketId='$ticketId'}");
        $this->assignCommonVariables();
        $this->assign('ticketId', $ticketId);
        // Ticket content
        $_GET['ticket_id']  =   $ticketId;
        $ctrlTicket =   new C_Ticket();
        $content    =   json_decode($ctrlTicket->actionViewOpenTicketAjax(), true);
        $this->assign('ticketContent', $content['ticket_body']);
        $result['result']['html']       =   $this->view->render('add_service.html');
        $result['result']['ticketName'] =   $content['ticket_name'];
        $this->logger->info("Finish action LoadServiceEditPageAjax {ticketId='$ticketId'}");

        return json_encode($result);
    }

    /**
     * Assign common variables for service adding page: departments, composite services, paraclinical services, and services of the logged in department.
     *
     */
    private function assignCommonVariables() {
        $login2Dept = $this->_me->get_department_id();
        $dept = Celini::newORDO('Department')->getDepartment($login2Dept);
        $this->assign('departments', array($login2Dept =>$dept['name']));

        $composite = Celini::newORDO('CompositeService');
        $compositeServiceList = $composite->listAll();
        $this->assign('compositeServiceList', $compositeServiceList);

        $paraClinicServices = Utils::getEnumArrayKey(EnumerationConstant::PARACLINIC_TYPE);
        $this->assign('paraClinicServices', $paraClinicServices);

        $_GET['department_id']  =   $login2Dept;
        $ctrlDepartment =   new C_Department();
        $serviceOptions =   $ctrlDepartment->actionFilterServiceAjax();
        $this->assign('serviceList', $serviceOptions);
    }
    
    public function actionFinishTicketAjax() {
        $ticketId		=	EnforceType::int($_GET['ticketId']);
        $result    =   array(
                    'error'     =>  array('code' => CoreErrorCode::NORMAL,
                                          'mess' => ''),
                    'result'    =>  ''
        );
        $this->logger->info("Start action FinishTicketAjax {ticketId=''$ticketId'}");
        try {
        	// Finish ticket
        	OutPatientFlowProcessor::closeItems($ticketId);
        	// Add the first ticket item to Cashier queue
        	$firstItemId	=	ORDataObject::factory('Ticket')->getLastTicketItem($ticketId);
        	$this->logger->debug("First ticket item of ticket {ticketId='$ticketId'}:  '$firstItemId'");
        	$cashierQueue  	=   AbsQueue::getQueue(AbsQueue::CASHIER);
        	$cashierQueue->addTicketItem($firstItemId);
        	$objQueueItem   =   QueueItem::fromTicketItemId($firstItemId);
            $nextRoom       =   Celini::newORDO('Room', $objQueueItem->get('room_id'))->getLocalizedText('name');
        	$result['result']['nextRoom']  		=   $nextRoom;
        	$result['result']['redirectLink']   =   Celini::link('renderQueue', 'Queue');
           
        }
        catch (Exception $ex) {
            $result['error']['code']    =   CoreErrorCode::COMMON_ERROR;
            $result['error']['mess']    =   CoreErrorCode::getErrorMess(CoreErrorCode::COMMON_ERROR);
            $this->logger->error("Action FinishTicketAjax failed. Error message: " . $ex->getMessage());
        }
        $this->logger->info("Start action FinishTicketAjax {ticketId=''$ticketId'}");

        return json_encode($result);
	}
}
?>